// 17 18
#pragma once
#include <memory> //智能指针
#include "noncopyable.h"
#include <functional>
#include "Timestamp.h" //因为要确定TimeStamp的大小，所以不能使用前置声明
//前置声明
class EventLoop;


/*
封装了sockfd和感兴趣的事件，EPOLLIN EPOLLOUT事件
还绑定了Poller返回的具体事件
*/
class Channel : noncopyable {
    public:
    //回调函数
        typedef std::function<void()> EventCallback; // or use using EventCallback = std::function<void()>;
        typedef std::function<void(Timestamp)> ReadEventCallback; 

        Channel(EventLoop *loop, int fd);
        ~Channel();

        // fd得到poller通知后，处理事件的，调用相应的回调方法
        void handleEvent(Timestamp receiveTime);

        // 设置回调函数对象
        void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); } // move：将左值转为右值，减少赋值资源消耗
        void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
        void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
        void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }

        // 防止当Channel手动remove时，Channel还在执行回调操作
        void tie(const std::shared_ptr<void> &);


        int fd() const { return fd_; }
        int events() const { return events_; }
        void set_revents(int revt) { revents_ = revt; }
        

        // 设置fd相应的事件状态
        void enableReading() { events_ |= KReadEvent; update(); } // update()应该是执行epoll_ctl()
        void disableReading() { events_ &= ~KReadEvent; update(); }
        void enableWriting() { events_ |= KWriteEvent; update(); }
        void disableWriting() { events_ &= ~KWriteEvent; update(); }
        void disableAll() { events_ = KNoneEvent; update(); }

        // 返回fd当前感兴趣的事件
        bool isNonEvent() const { return events_ == KNoneEvent; }
        bool isWriting() const { return events_ & KWriteEvent; }
        bool isReading() const { return events_ & KReadEvent; }

        // for poller
        int index() { return index_; }
        void set_index(int idx) { index_ = idx; }

        EventLoop* ownerLoop() { return loop_; } // 查看这个channel属于哪一个event loop
        void remove(); //删除channel

    private:
        void update();
        void handleEventWithGuard(Timestamp receiveTime);

        static const int KNoneEvent;
        static const int KReadEvent;
        static const int KWriteEvent;
        
        EventLoop *loop_;// channel属于loop
        const int fd_; //Poller 监听的sock对象
        int events_; //注册fd感兴趣的事件
        int revents_; //Poller返回的具体发生的事件
        int index_; // 标识当前channel是否已经加入到poller的监听中

        std::weak_ptr<void> tie_;
        bool tied_;

        //因为Channel能获取fd最终发生的具体事件revents，所以也负责调用相应的回调操作
        ReadEventCallback readCallback_;
        EventCallback writeCallback_;
        EventCallback closeCallback_;
        EventCallback errorCallback_;
};